import { ObjectId } from 'mongodb'
import {
  IUser,
  Gender,
  Relevance,
  Dynamic,
  IBooks,
  Remark,
  Dingdan,
  Identity,
  UserStatus
} from '../types'
import { stats } from '../stats'
import * as db from '../db'
import * as crypto from 'crypto'
import { addSome, checkSome, dealmid, removeSome, sha } from './tools'

async function Sum(userId: ObjectId, type: Relevance) {
  return await db.connectCollection.find({ userId, type }).count()
}

// 获取登录用户信息
export async function userInfo(token: string) {
  const tokens = await db.tokenCollection.findOne({ userToken: token })
  if (tokens.userId) {
    const user = await db.userCollection.findOne(
      { _id: tokens.userId },
      { projection: { password: 0 } }
    )
    if (!user) throw stats.ERR_NOT_FOUND
    const userId = user._id
    const following = await Sum(userId, Relevance.Myfocus)
    const followers = await Sum(userId, Relevance.Focusme)
    return {
      ...user,
      following,
      followers
    }
  }
}

// 获取用户信息
export async function otherUserInfo(destId: string, userId?: ObjectId) {
  const user = await db.userCollection.findOne({ _id: new ObjectId(destId) })
  if (!user) throw stats.ERR_NOT_FOUND
  const other = new ObjectId(destId)
  let islove = false
  if (userId) {
    const mine = userId
    const res = await checkSome(mine, other, Relevance.Myfocus)
    if (res) islove = true
  }
  const following = await Sum(other, Relevance.Myfocus)
  const followers = await Sum(other, Relevance.Focusme)
  return {
    ...user,
    islove,
    following,
    followers,
    password: undefined as string
  }
}

// 注册
export async function register(record: IUser) {
  const user = await db.userCollection.findOne({
    username: record.username
  })
  if (user) {
    throw stats.ERR_NOT_FOUND
  } else {
    const pwd = sha(record.password)
    const nickname = record.username.substring(0, 1) + '同学'
    const result = await db.userCollection.insertOne({
      ...record,
      nickname,
      password: pwd,
      avatar:
        'http://p1.music.126.net/eoLj-AoG-P9Rrc_ph3FH9Q==/109951166591159226.jpg',
      gender: Gender.null,
      qqnumber: 13000001111,
      registerTime: Date.now(),
      mdb: 10,
      role: Identity.Student,
      state: UserStatus.Normal,
      major: ['未选'],
      signature: '笃信好学,自然宽和'
    })
    return result.acknowledged
  }
}

// 登录
export async function login(record: IUser) {
  const user = await db.userCollection.findOne({
    username: record.username
  })
  if (!user) throw stats.ERR_NOT_FOUND
  const pass = sha(record.password)
  if (!user || pass !== user.password) throw stats.ERR_LOGIN_FAILED
  const token = crypto.randomBytes(12).toString('hex')
  await db.tokenCollection.insertOne({
    _id: null,
    userToken: token,
    userId: user._id,
    createdAt: new Date()
  })
  return {
    token,
    user
  }
}

// 修改用户密码
export async function updatepwd(
  userId: ObjectId,
  value: { oldpwd: string; newpwd: string }
) {
  const user = await db.userCollection.findOne({ _id: userId })
  if (user.password !== sha(value.oldpwd)) throw stats.ERR_old_PASSWORD
  if (user.password === sha(value.newpwd)) throw stats.ERR_PASSWORD
  await db.userCollection.findOneAndUpdate(
    { _id: userId },
    { $set: { password: sha(value.newpwd) } }
  )
}

// 处理关注
export async function dealfocus(
  userId: ObjectId,
  destId: string,
  flag: boolean
) {
  if (userId.equals(destId)) throw stats.ERR_FIRBID_FOLLOW
  const mine = new ObjectId(userId)
  const other = new ObjectId(destId)
  const res = await checkSome(mine, other, Relevance.Myfocus)
  if (flag) {
    if (res) return '已关注'
    await addSome(mine, other, Relevance.Myfocus)
    await addSome(other, mine, Relevance.Focusme)
    return '关注成功'
  } else {
    await removeSome(mine, other, Relevance.Myfocus)
    await removeSome(other, mine, Relevance.Focusme)
    return '已移取消关注'
  }
}

// 登出
export function logout(token: string) {
  return db.tokenCollection.findOneAndDelete({ userToken: token })
}

// 更新用户信息
export async function updateinfo(userId: ObjectId, value: IUser) {
  await db.userCollection.findOneAndUpdate(
    { _id: new ObjectId(userId) },
    {
      $set: { ...value }
    }
  )
}

// 获取用户列表 关注的用户
export async function ulist(value: any) {
  const { destId, skip, limit, flag } = value
  const type = flag ? Relevance.Myfocus : Relevance.Focusme
  const { destIds, total } = await dealmid(
    new ObjectId(destId),
    type,
    skip,
    limit
  )
  const list = await db.userCollection
    .aggregate([
      { $match: { _id: { $in: destIds } } },
      {
        $project: {
          _id: 1,
          nickname: 1,
          avatar: 1,
          signature: 1
        }
      }
    ])
    .toArray()
  return { list, total }
}

// 动态列表. (随心贴? 点赞的随心贴), 关注的用户 我发布的
export async function dylist(value: any) {
  const { userId: userid, skip, limit } = value
  const userId = new ObjectId(userid)
  const all = {
    userId,
    $or: [
      { type: Relevance.Myfocus },
      { type: Relevance.Mythumb },
      { type: Relevance.Myissue },
      { type: Relevance.Remark },
      { type: Relevance.likeRemark }
    ]
  }
  const justRemark = { userId, type: Relevance.Remark }
  const match = value?.type === Relevance.Remark ? justRemark : all
  const total = await db.connectCollection.find(match).count()
  const mids = await db.connectCollection
    .aggregate([
      { $match: match },
      { $sort: { time: -1 } },
      { $skip: skip },
      { $limit: limit },
      {
        $project: {
          destId: 1,
          type: 1,
          time: 1
        }
      }
    ])
    .toArray()

  const list: Dynamic[] = []
  let dynamic: IUser | IBooks | Remark | IBooks[]

  for (const mid of mids) {
    if (mid.type === Relevance.Myfocus) {
      dynamic = await db.userCollection.findOne(
        { _id: mid.destId },
        { projection: { avatar: 1, nickname: 1, signature: 1 } }
      )
      list.push({ createAt: mid.time, type: mid.type, dynamic })
      // } else if (mid.type === Relevance.Maichu) {
      //   // 小复杂
      //   const res = await db.dingdansCollection.findOne(
      //     { _id: mid.destId },
      //     { projection: { bookIds: 1 } }
      //   )
      //   const dynamic = await db.booksCollection
      //     .find(
      //       { _id: { $in: res.bookIds }, publisher: mid.destId },
      //       { projection: { title: 1, banner: 1, content: 1 } }
      //     )
      //     .toArray()
      //   list.push({ createAt: mid.time, type: mid.type, dynamic })
    } else if (
      mid.type === Relevance.Remark ||
      mid.type === Relevance.likeRemark
    ) {
      dynamic = await db.remarksCollection.findOne(
        { _id: mid.destId },
        { projection: { content: 1, rate: 1, thumbs: 1, bookId: 1 } }
      )
      list.push({ createAt: mid.time, type: mid.type, dynamic })
    } else {
      dynamic = await db.booksCollection.findOne(
        { _id: mid.destId },
        { projection: { title: 1, banner: 1, content: 1 } }
      )
      list.push({ createAt: mid.time, type: mid.type, dynamic })
    }
  }
  return { list, total }
}

export async function cars(userId: ObjectId) {
  return db.connectCollection.find({ userId, type: Relevance.Mycars }).count()
}
